package com.lan.parse;

import com.lan.ScriptContext;
import com.lan.antlr.ScriptBaseListener;
import com.lan.antlr.ScriptParser;
import com.lan.model.symbol.Clazz;
import com.lan.model.symbol.Function;
import com.lan.model.symbol.Scope;
import com.lan.model.symbol.Variable;
import org.antlr.v4.runtime.ParserRuleContext;
import org.apache.commons.lang3.StringUtils;

import java.util.Collections;
import java.util.List;


public class TypeResolver extends ScriptBaseListener {

    private ScriptContext context;

    //是否把本地变量加入符号表
    private boolean enterLocalVariable = false;

    public TypeResolver(ScriptContext context) {
        this.context = context;
    }

    public TypeResolver(ScriptContext context, boolean enterLocalVariable) {
        this.context = context;
        this.enterLocalVariable = enterLocalVariable;
    }

    private void print(ParserRuleContext ctx, String name) {
        System.out.println(ctx.getRuleIndex() + " :   " + ctx.toString() + "   " + (StringUtils.isNotBlank(name) ? name : "") + " " + (StringUtils.isNotBlank(ctx.getText()) ? ctx.getText() : ""));
    }


    @Override
    public void enterVariableDeclarator(ScriptParser.VariableDeclaratorContext ctx) {
        ScriptParser.VariableDeclaratorIdContext id = ctx.variableDeclaratorId();
        if (id != null) {
            String name = id.name().getText();
            Scope scope = context.nodeOfScope(ctx);
            //第一步只把类的成员变量入符号表。在变量消解时，再把本地变量加入符号表，一边Enter，一边消解。
            if (scope instanceof Clazz || ctx.parent.parent instanceof ScriptParser.FormalParameterListContext || enterLocalVariable) {
                Variable variable = new Variable(name, scope, ctx);
                //变量查找
                if (Scope.getVariable(scope, name) == null) {
//                    context.log("Variable or parameter already Declared: " + name, ctx);
                    scope.addSymbol(variable);
                    context.symbolOfNode(ctx, variable);
                }

            }
        }

//        if (ctx.ASSIGN() != null && ctx.variableInitializer() != null) {
//            ScriptParser.LiteralContext literalContext = getLiteralContext(ctx);
//        }
    }


    private ScriptParser.LiteralContext getLiteralContext(ScriptParser.VariableDeclaratorContext ctx) {
        ScriptParser.VariableInitializerContext initializerContext = ctx.variableInitializer();
        if (initializerContext == null) {
            return null;
        }
        ScriptParser.ExpressionContext expressionContext = initializerContext.expression();
        if (expressionContext == null) {
            return null;
        }
        ScriptParser.PrimaryContext primaryContext = expressionContext.primary();
        if (primaryContext == null) {
            return null;
        }
        return primaryContext.literal();
    }


    /**
     * 设置函数的参数的类型，这些参数已经在enterVariableDeclaratorId中作为变量声明了，现在设置它们的类型
     *
     * @param ctx
     */
    @Override
    public void exitFormalParameterList(ScriptParser.FormalParameterListContext ctx) {
        List<ScriptParser.VariableDeclaratorIdContext> list = ctx.variableDeclaratorId();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                // 设置参数类型
                Variable variable = (Variable) context.symbolOfNode(ctx.variableDeclaratorId(i));
                // 添加到函数的参数列表里
                Scope scope = context.scopeOfNode(ctx);
                if (scope instanceof Function) {
                    //TODO 从目前的语法来看，只有function才会使用FormalParameter
                    ((Function) scope).getParameters().add(variable);
                }
            }
        }
    }

}




















